#include <stdlib.h>
#include "list.h"

// Returns last Item in the list [возвращает указатель на конец списка]
list::Item* list::GetLastItem(void)
{
	return LastItem;
}

// Returns last item in the list [возвращает указатель на последний элемент списка]
void* list::getLastItem(void)
{
	if(LastItem)
		return LastItem->ptr;
	return NULL;
}

// Returns Start [возвращает указатель на начало спика]
list::Item* list::GetItems(void)
{
	if(blocked) return NULL;

	return Start;
}

// Returns number of elements in the list [возращает количество элементов]
long list::Count(void)
{
	return inf_count;
}

// Adds an element to a list [добавляет элемент в список]
list::Item* list::Add(void* ptr)
{
	Item* I=new Item;
	I->index=inf_count;	
	I->ptr=ptr;

	inf_count++;
	I->List=this;

	if(LastItem==NULL)
		LastItem=I;
	else
	{
		I->prev=LastItem;
		LastItem->next=I;	
	}

	if(!Start)		Start=I;

	LastItem=I;
	return I;
}

// Adds an element to a list [добавляет элемент в список, первым]
list::Item* list::AddFirst(void* ptr)
{
	Item* I;
	for(list::Item* I=Start; I!=NULL; I=I->next)
		I->index++;

	I=new Item;
	I->index=0;	
	I->ptr=ptr;

	inf_count++;
	I->List=this;
	
	if(!Start)
	{
		Start=I;
		LastItem=I;
	}
	else
	{
		Item* formerStart=Start;
		formerStart->prev=I;
		I->next=formerStart;
		Start=I;
	}
	
	return I;
}

// Removes item from list [удаляет элемент из списка]
bool list::RemoveItem(list::Item* I)
{
	if(!I)		return false;
	if(I->List==this)
	{
		blocked=true;

		if(LastItem==I)
			LastItem=I->prev;

		if(I->prev)	I->prev->next=I->next;
		if(I->next)	I->next->prev=I->prev;

		if(!I->prev) Start=I->next;
		delete I;
		inf_count--;
		blocked=false;
		return true;
	}
	return false;
}

// Removes item from list [удаляет элемент из списка]
bool list::RemoveItem(void* I)
{
	list::Item* U=GetItemByPointer(I);
	if(U)
	{
		RemoveItem(U);
		return true;
	}
	return false;
}

// Removes item from list [удаляет элемент из списка]
bool list::removeItem(long index)
{
	list::Item* U=GetItem(index);
	if(U)
	{
		RemoveItem(U);
		return true;
	}
	return false;
}

// Clears the list [удаляет все элементы списка]
void list::Clear(void)
{
	Item* Next=Start;
	for(list::Item* I=Start; I!=NULL; I=Next)
	{
		Next=I->next;
		delete I;
	}
	Start=NULL;
	LastItem=NULL;
	inf_count=0;
}

list::list()
{
	LastItem=NULL;
	Start=NULL;
	inf_count=0;
	blocked=false;
}

void list::AppendItem(list::Item* I)
{
	I->List=this;
	I->next=NULL;
	if(Start)
	{
		LastItem->next=I;
		I->prev=LastItem;
		inf_count++;
	}
	else
	{
		Start=I;
		I->prev=NULL;
		inf_count++;
	}
}

void list::EjectItem(list::Item* I)
{
	if(!I)		return;
	if(I->List==this)
	{
		blocked=true;

		if(LastItem==I)
			LastItem=I->prev;

		if(I->prev)	I->prev->next=I->next;
		if(I->next)	I->next->prev=I->prev;

		if(!I->prev) Start=I->next;
		inf_count--;
		blocked=false;
	}
}

list::~list()
{
	Clear();	
}

// Finds an element in the list by its id [поиск элемента по идентификатору]
list::Item* list::FindItem(long id)
{
	for(list::Item* I=Start; I!=NULL; I=I->next)
	{
		if(I->id==id)
			return I;
	}
	return NULL;
}

// Finds an element in the list by its id [поиск элемента по идентификатору]
list::Item* list::GetItemByPointer(void* ptr)
{
	for(list::Item* I=Start; I!=NULL; I=I->next)
	{
		if(I->ptr==ptr)
			return I;
	}
	return NULL;
}

// Finds an element in the list by its id [поиск элемента по идентификатору]
void* list::findItem(long id)
{
	if(blocked) return NULL;

	for(list::Item* I=Start; I!=NULL; I=I->next)
	{
		if(I->id==id)
			return I->ptr;
	}
	return NULL;
}


// Finds an element in the list by its index [поиск элемента по индексу]
list::Item* list::GetItem(long index)
{
	long Index=0;
	for(list::Item* I=Start; I!=NULL; I=I->next)
	{
		if(Index==index)
			return I;
		Index++;
	}
	return NULL;
}

// Finds an element in the list by its index [поиск элемента по индексу]
void* list::getItem(long index)
{
	if(blocked) return NULL;

	long Index=0;
	for(list::Item* I=Start; I!=NULL; I=I->next)
	{
		if(Index==index)
			return I->ptr;
		Index++;
	}
	return NULL;
}

/// --- Item of the list [элемент списка]

list::Item::Item()
{
	ptr=NULL;
	List=NULL;
	prev=NULL;
	next=NULL;
	id=-1;
	index=-1;
}

// Sets item's id [устанавливает идентификатор элемента]
bool list::Item::SetID(long id)
{
	if(List)
	{
		if(List->FindItem(id))
			return false;
	}
	this->id=id;
	return true;
}